﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Diagnostics;
using WiiGeeDotNet.events;

namespace WiiGeeDotNet.filter
{
  public class MotionDetectFilter : Filter
  {
    public delegate void MotionStartedDelegate(MotionStartEvent _event);
    public event MotionStartedDelegate MotionStarted;

    public delegate void MotionStoppedDelegate(MotionStopEvent _event);
    public event MotionStoppedDelegate MotionStopped;

    private int m_motionchangetime;
    private bool m_nowinmotion;
    private Stopwatch m_timer;

    /// <summary>
    /// Detects wheather the wiimote receives acceleration or not and
    /// raises an event, if the device starts or stops. This is actual a
    /// null filter, not manipulating anything. But looks pretty good in
    /// this datatype since it could be removed easily.
    /// </summary>
    public MotionDetectFilter()
      : base()
    {
      m_timer = new Stopwatch();
      this.Reset();
    }


    public new void Reset()
    {
      base.Reset();
      m_timer.Reset();
      m_timer.Start();
      this.m_nowinmotion = false;
      this.m_motionchangetime = 190;
    }

    public override double[] FilterVector(double[] vector)
    {
      if (this.m_nowinmotion &&
          (m_timer.ElapsedMilliseconds >= this.m_motionchangetime))
      {
        this.m_nowinmotion = false;
        if (this.MotionStopped != null)
        {
          MotionStopped(new MotionStopEvent());
        }
        //this.device.fireMotionStopEvent();
      } // fi

      return FilterAlgorithm(vector);
    }

    public override double[] FilterAlgorithm(double[] vector)
    {
      if (vector != null)
      {
        //this.motionstartstamp = System.currentTimeMillis();
        m_timer.Reset();
        m_timer.Start();
        if (!this.m_nowinmotion)
        {
          this.m_nowinmotion = true;
          //this.motionstartstamp = System.currentTimeMillis();
          if (this.MotionStarted != null)
          {
            MotionStarted(new MotionStartEvent());
          }
          //this.device.fireMotionStartEvent();
        }
      }

      return vector;
    }

    /// <summary>
    /// Defines the time the wiimote has to be in idle state before a new motion change
    /// event appears. The default value 500ms should work well, only change it if you are sure
    /// about what you're doing.
    /// </summary>
    public int Motionchangetime
    {
      get { return m_motionchangetime; }
      set { m_motionchangetime = value; }
    }
  }
}
